//
//  cal_determinant.c
//  linear_algebra
//
//  Created by zhangnan on 2025/3/21.
//

#include "cal_determinant.h"
#include "math.h"
#include <stdlib.h>
#include "../utils/common.h"

/*
 按行展开计算double类型行列式
 */
double cal_double_determinant_by_row(DETERMINANT_DOUBLE_TYPE param){
    if(param.rows==1){
        return param.array[0];
    }else if(param.rows==2){
        return param.array[0]*param.array[3]-param.array[1]*param.array[2];
    }else{
        double result=0;
        for(int i=0;i<param.rows;i++){
            int *arr;
            // 使用 malloc 分配内存
            arr = (double *)malloc(pow(param.rows-1,2) * sizeof(double));
            cal_lower_double_determinant(arr, param, i);
            result+=param.array[i]*(double)pow(-1,i+2)*cal_double_determinant_by_row(new_double_determinant(arr, param.rows-1));
            free(arr);
        }
        return result;
    }
}

/*
 按行展开计算int类型行列式
 */
int cal_int_determinant_by_row(DETERMINANT_INT_TYPE param){
    if(param.rows==1){
        return param.array[0];
    }else if(param.rows==2){
        return param.array[0]*param.array[3]-param.array[1]*param.array[2];
    }else{
        int result=0;
        for(int i=0;i<param.rows;i++){
            int *arr;
            // 使用 malloc 分配内存
            arr = (int *)malloc(pow(param.rows-1,2) * sizeof(int));
            cal_lower_int_determinant(arr, param, i);
            result+=param.array[i]*pow(-1,i+2)*cal_int_determinant_by_row(new_int_determinant(arr, param.rows-1));
            free(arr);
        }
        return result;
    }
}


/*
 计算按照排列方式直接计算行列式的值(double)
 */
double cal_double_determinant_by_arrange(DETERMINANT_DOUBLE_TYPE params){
    int num=params.rows;
    // 生成原始数组
    int *arr=(int *)malloc(num*sizeof(int));
    for(int i=0;i<num;i++){
        arr[i]=i+1;
    }
    // 计算num的阶乘
    int length=factorial(num);
    int *result_arr=(int *)malloc(length* sizeof(int));
    // 生成排列组合
    permute_index=0;
    permute(arr,0,num-1,result_arr);
    // 计算行列式的值
    double result=0;
    for(int i=0;i<length;i++){
        double temp=1;
        for(int j=0;j<num;j++){
            temp=temp*get_double_determinant_value(params, j, result_arr[i*num+j]-1);
        }
        temp=temp*(double)cal_cofactor‌‌_symbol(result_arr, num, i);
        result+=temp;
    }
    free(arr);
    free(result_arr);
    return result;
}

/*
 计算按照排列方式直接计算行列式的值(int)
 */
double cal_int_determinant_by_arrange(DETERMINANT_INT_TYPE params){
    int num=params.rows;
    // 生成原始数组
    int *arr=(int *)malloc(num*sizeof(int));
    for(int i=0;i<num;i++){
        arr[i]=i+1;
    }
    // 计算num的阶乘
    int length=factorial(num);
    int *result_arr=(int *)malloc(length*num* sizeof(int));
    // 生成排列组合
    permute_index=0;
    permute(arr,0,num-1,result_arr);
    
    for(int m=0;m<length*num;m++){
        printf("%d,",result_arr[m]);
    }
    // 计算行列式的值
    int result=0;
    for(int i=0;i<length;i++){
        int temp=1;
        for(int j=0;j<num;j++){
            temp=temp*get_int_determinant_value(params, j, result_arr[i*num+j]-1);
        }
        temp=temp*cal_cofactor‌‌_symbol(result_arr, num, i);
        result+=temp;
    }
    free(arr);
    free(result_arr);
    return result;
}


/**
 计算代数余子式的符号
 params 为排列数组
 cols为每个排列的列数
 index为第几个排列
 */
int cal_cofactor‌‌_symbol(int *params,int cols,int index){
    int count=0;
    for(int i=cols*(index);i<cols*(index+1);i++){
        
        for(int j=i;j<cols*(index+1);j++){
            
            if(params[i]>params[j]){
                count++;
            }
        }
    }
    
    if(count%2==0){
        return 1;
    }else{
        return -1;
    }
}


